package com.generator.mcp;

import com.generator.model.TableInfo;
import com.generator.parser.SqlDdlParser;
import com.generator.service.CloudStorageService;
import com.generator.service.FreemarkerCrudGenerator;
import com.generator.service.ZipService;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 增强版代码生成工具提供者
 * 支持交互式参数收集、预览、生成、打包和云存储上传
 * 
 * @author Generator
 * @since 2024-01-01
 */
@Component
public class EnhancedGeneratorToolProvider {

    private final SqlDdlParser sqlDdlParser;
    private final FreemarkerCrudGenerator crudGenerator;
    private final ZipService zipService;
    private final CloudStorageService cloudStorageService;

    @Autowired
    public EnhancedGeneratorToolProvider(SqlDdlParser sqlDdlParser, 
                                       FreemarkerCrudGenerator crudGenerator,
                                       ZipService zipService,
                                       CloudStorageService cloudStorageService) {
        this.sqlDdlParser = sqlDdlParser;
        this.crudGenerator = crudGenerator;
        this.zipService = zipService;
        this.cloudStorageService = cloudStorageService;
    }

    @Tool(name = "validate_ddl", description = "校验DDL语句并返回解析的表信息")
    public Map<String, Object> validateDdl(
            @ToolParam(description = "CREATE TABLE DDL语句") String ddlSql) {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            boolean isValid = sqlDdlParser.validateDdl(ddlSql);
            result.put("valid", isValid);
            result.put("message", isValid ? "DDL语句有效" : "DDL语句无效");
            
            if (isValid) {
                List<TableInfo> tables = sqlDdlParser.parseDdl(ddlSql);
                result.put("tables", tables);
                result.put("tableCount", tables.size());
                
                // 提供下一步建议
                result.put("nextSteps", List.of(
                    "使用 preview_code 预览生成的代码",
                    "使用 generate_code 生成代码文件",
                    "使用 generate_and_upload 生成代码并上传到云存储"
                ));
            }
            
        } catch (Exception e) {
            result.put("valid", false);
            result.put("message", "DDL解析失败: " + e.getMessage());
        }
        
        return result;
    }

    @Tool(name = "collect_generation_params", description = "收集代码生成所需的参数信息")
    public Map<String, Object> collectGenerationParams() {
        Map<String, Object> result = new HashMap<>();
        
        result.put("message", "请提供以下参数来生成代码:");
        result.put("requiredParams", Map.of(
            "ddlSql", "CREATE TABLE DDL语句",
            "packageName", "Java包名 (例如: com.example.demo)",
            "author", "作者名称",
            "outputPath", "输出路径 (例如: ./generated-code)"
        ));
        
        result.put("optionalParams", Map.of(
            "previewMode", "是否仅预览代码 (true/false, 默认false)",
            "uploadToCloud", "是否上传到云存储 (true/false, 默认false)"
        ));
        
        result.put("examples", Map.of(
            "packageName", "com.mycompany.project",
            "author", "张三",
            "outputPath", "./my-generated-code"
        ));
        
        result.put("cloudStorageStatus", cloudStorageService.isAvailable() ? 
            "云存储已配置，可以上传文件" : "云存储未配置，无法上传文件");
        
        return result;
    }

    @Tool(name = "preview_code", description = "预览生成的代码，返回代码块供前端渲染")
    public Map<String, Object> previewCode(
            @ToolParam(description = "CREATE TABLE DDL语句") String ddlSql,
            @ToolParam(description = "Java包名") String packageName,
            @ToolParam(description = "作者名称") String author,
            @ToolParam(description = "输出路径（可选）") String outputPath) {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 验证DDL
            if (!sqlDdlParser.validateDdl(ddlSql)) {
                result.put("success", false);
                result.put("message", "DDL语句无效");
                return result;
            }
            
            // 解析表信息
            List<TableInfo> tables = sqlDdlParser.parseDdl(ddlSql);
            if (tables.isEmpty()) {
                result.put("success", false);
                result.put("message", "未找到有效的表定义");
                return result;
            }
            
            TableInfo tableInfo = tables.get(0);
            
            // 设置默认值
            if (packageName == null || packageName.trim().isEmpty()) {
                packageName = "com.example.demo";
            }
            if (author == null || author.trim().isEmpty()) {
                author = "Generator";
            }
            
            // 生成代码（仅内存中，不写入文件）
            Map<String, String> generatedFiles = crudGenerator.generateCrudCode(
                tableInfo, packageName, author, outputPath != null ? outputPath : "./temp");
            
            result.put("success", true);
            result.put("mode", "preview");
            result.put("tableInfo", Map.of(
                "tableName", tableInfo.getTableName(),
                "entityName", tableInfo.getEntityName(),
                "comment", tableInfo.getTableComment()
            ));
            
            // 格式化代码块供前端渲染
            Map<String, Map<String, String>> codeBlocks = new HashMap<>();
            generatedFiles.forEach((fileType, code) -> {
                codeBlocks.put(fileType, Map.of(
                    "language", getLanguageForFileType(fileType),
                    "code", code,
                    "fileName", getFileNameForType(fileType, tableInfo.getEntityName())
                ));
            });
            
            result.put("codeBlocks", codeBlocks);
            result.put("parameters", Map.of(
                "packageName", packageName,
                "author", author,
                "outputPath", outputPath != null ? outputPath : "未指定"
            ));
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "代码预览失败: " + e.getMessage());
        }
        
        return result;
    }

    @Tool(name = "generate_code", description = "生成代码文件到指定目录")
    public Map<String, Object> generateCode(
            @ToolParam(description = "CREATE TABLE DDL语句") String ddlSql,
            @ToolParam(description = "Java包名") String packageName,
            @ToolParam(description = "作者名称") String author,
            @ToolParam(description = "输出路径") String outputPath) {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 验证参数
            if (outputPath == null || outputPath.trim().isEmpty()) {
                result.put("success", false);
                result.put("message", "输出路径不能为空");
                return result;
            }
            
            // 验证DDL
            if (!sqlDdlParser.validateDdl(ddlSql)) {
                result.put("success", false);
                result.put("message", "DDL语句无效");
                return result;
            }
            
            // 解析表信息
            List<TableInfo> tables = sqlDdlParser.parseDdl(ddlSql);
            if (tables.isEmpty()) {
                result.put("success", false);
                result.put("message", "未找到有效的表定义");
                return result;
            }
            
            TableInfo tableInfo = tables.get(0);
            
            // 设置默认值
            if (packageName == null || packageName.trim().isEmpty()) {
                packageName = "com.example.demo";
            }
            if (author == null || author.trim().isEmpty()) {
                author = "Generator";
            }
            
            // 生成代码文件
            Map<String, String> generatedFiles = crudGenerator.generateCrudCode(
                tableInfo, packageName, author, outputPath);
            
            result.put("success", true);
            result.put("mode", "generate");
            result.put("message", "代码生成成功");
            result.put("outputPath", outputPath);
            result.put("fileCount", generatedFiles.size());
            result.put("generatedFiles", generatedFiles.keySet());
            result.put("tableInfo", Map.of(
                "tableName", tableInfo.getTableName(),
                "entityName", tableInfo.getEntityName()
            ));
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "代码生成失败: " + e.getMessage());
        }
        
        return result;
    }

    @Tool(name = "generate_and_upload", description = "生成代码、打包为ZIP并上传到云存储")
    public Map<String, Object> generateAndUpload(
            @ToolParam(description = "CREATE TABLE DDL语句") String ddlSql,
            @ToolParam(description = "Java包名") String packageName,
            @ToolParam(description = "作者名称") String author) {
        
        Map<String, Object> result = new HashMap<>();
        File zipFile = null;
        
        try {
            // 检查云存储是否可用
            if (!cloudStorageService.isAvailable()) {
                result.put("success", false);
                result.put("message", "云存储未配置或未启用，请检查环境变量配置");
                result.put("requiredEnvVars", List.of(
                    "CLOUD_STORAGE_ENABLED=true",
                    "CLOUD_STORAGE_S3_ENDPOINT (可选，用于MinIO等)",
                    "CLOUD_STORAGE_S3_ACCESS_KEY",
                    "CLOUD_STORAGE_S3_SECRET_KEY",
                    "CLOUD_STORAGE_S3_BUCKET",
                    "CLOUD_STORAGE_S3_REGION (可选，默认us-east-1)"
                ));
                return result;
            }
            
            // 验证DDL
            if (!sqlDdlParser.validateDdl(ddlSql)) {
                result.put("success", false);
                result.put("message", "DDL语句无效");
                return result;
            }
            
            // 解析表信息
            List<TableInfo> tables = sqlDdlParser.parseDdl(ddlSql);
            if (tables.isEmpty()) {
                result.put("success", false);
                result.put("message", "未找到有效的表定义");
                return result;
            }
            
            TableInfo tableInfo = tables.get(0);
            
            // 设置默认值
            if (packageName == null || packageName.trim().isEmpty()) {
                packageName = "com.example.demo";
            }
            if (author == null || author.trim().isEmpty()) {
                author = "Generator";
            }
            
            // 创建临时目录
            String tempDir = System.getProperty("java.io.tmpdir") + "/generated-code-" + System.currentTimeMillis();
            
            // 生成代码文件
            Map<String, String> generatedFiles = crudGenerator.generateCrudCode(
                tableInfo, packageName, author, tempDir);
            
            // 打包为ZIP
            String zipFileName = tableInfo.getEntityName() + "_generated_code";
            zipFile = zipService.createZipFile(tempDir, zipFileName);
            
            // 上传到云存储
            String downloadUrl = cloudStorageService.uploadFile(zipFile, zipFile.getName());
            
            result.put("success", true);
            result.put("mode", "generate_and_upload");
            result.put("message", "代码生成并上传成功");
            result.put("downloadUrl", downloadUrl);
            result.put("zipFileName", zipFile.getName());
            result.put("fileCount", generatedFiles.size());
            result.put("tableInfo", Map.of(
                "tableName", tableInfo.getTableName(),
                "entityName", tableInfo.getEntityName()
            ));
            result.put("parameters", Map.of(
                "packageName", packageName,
                "author", author
            ));
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "代码生成和上传失败: " + e.getMessage());
        } finally {
            // 清理临时文件
            if (zipFile != null) {
                zipService.cleanupZipFile(zipFile);
            }
        }
        
        return result;
    }

    @Tool(name = "check_cloud_storage", description = "检查云存储配置状态")
    public Map<String, Object> checkCloudStorage() {
        Map<String, Object> result = new HashMap<>();
        
        boolean available = cloudStorageService.isAvailable();
        result.put("available", available);
        result.put("message", available ? "云存储已配置并可用" : "云存储未配置或不可用");
        
        if (!available) {
            result.put("requiredEnvVars", Map.of(
                "CLOUD_STORAGE_ENABLED", "设置为 true 启用云存储",
                "CLOUD_STORAGE_S3_ACCESS_KEY", "S3访问密钥",
                "CLOUD_STORAGE_S3_SECRET_KEY", "S3秘密密钥",
                "CLOUD_STORAGE_S3_BUCKET", "S3存储桶名称",
                "CLOUD_STORAGE_S3_ENDPOINT", "自定义端点（可选，用于MinIO等）",
                "CLOUD_STORAGE_S3_REGION", "S3区域（可选，默认us-east-1）"
            ));
            
            result.put("examples", Map.of(
                "AWS S3", "不需要设置ENDPOINT",
                "MinIO", "ENDPOINT=http://localhost:9000",
                "阿里云OSS", "ENDPOINT=https://oss-cn-hangzhou.aliyuncs.com"
            ));
        }
        
        return result;
    }

    /**
     * 获取文件类型对应的语言标识
     */
    private String getLanguageForFileType(String fileType) {
        if (fileType.equalsIgnoreCase("MapperXml")) {
            return "xml";
        }else {
            return "java";
        }
    }

    /**
     * 获取文件类型对应的文件名
     */
    private String getFileNameForType(String fileType, String entityName) {
        return switch (fileType) {
            case "Entity" -> entityName + ".java";
            case "Mapper" -> entityName + "Mapper.java";
            case "MapperXml" -> entityName + "Mapper.xml";
            case "Service" -> entityName + "Service.java";
            case "ServiceImpl" -> entityName + "ServiceImpl.java";
            case "Controller" -> entityName + "Controller.java";
            default -> fileType + ".java";
        };
    }
}